/*
 *  Copyright 2004 Blandware (http://www.blandware.com)
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.blandware.atleap.model.core;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Iterator;

/**
 * <p>Locale for content. This represents some language for which application
 * will have support. For each localized content (like {@link ContentFieldValue})
 * Content Locale is specified. It's also attached to {@link ContentDocument}s.
 * </p>
 * <p>
 * Each content locale may be <em>active</em> or <em>inactive</em>. Active
 * content locale is one that is actually used. Content field values with content
 * locale which is inactive are not displayed to user. It's convenient when you
 * need to add some language: until everything is ready, it will be invisible.
 * </p>
 * <p>
 * Also, content locale may be <em>enabled</em> or <em>disabled</em>. Disabled
 * locale is visible only in content locales list; in other cases it's
 * invisible. Disabling a content locale is a way to avoid its deletion (so,
 * content for disabled locale is preserved) when locale is not needed yet.
 * When locale is disabled, it's usually made inactive too.
 * </p>
 * <p>
 * One of content locales is default. It's used when nothing was found for
 * requested content locale.
 * </p>
 * <p><a href="ContentLocale.java.html"><i>View Source</i></a>
 * </p>
 * <p/>
 *
 * @author Andrey Grebnev <a href="mailto:andrey.grebnev@blandware.com">&lt;andrey.grebnev@blandware.com&gt;</a>
 * @author Sergey Zubtsovskiy <a href="mailto:sergey.zubtsovskiy@blandware.com">&lt;sergey.zubtsovskiy@blandware.com&gt;</a>
 * @version $Revision: 1.37 $ $Date: 2007/12/11 14:23:43 $
 * @struts.form include-all="false" extends="BaseForm"
 * @hibernate.class table="`al_core_locale`" lazy="false"
 * @hibernate.cache usage="read-write"
 */
public class ContentLocale extends BaseObject implements Comparable {

    /**
     * Identifier of this content locale. It's based on standart. Examples are
     * en, ru, es.
     */
	protected String identifier;
    /**
     * Is this locale default
     */
	protected Boolean defaultInstance;
    /**
     * Is this locale active (may be used in application for displaying content)
     */
	protected Boolean active;
    /**
     * Is this locale enabled (may be used in application - at least for editing)
     */
    protected Boolean enabled;
    /**
     * List of CFVs with this locale
     */
	protected List contentFieldValues = new ArrayList();
    /**
     * List of content documents with this locale
     */
	protected List contentDocuments = new ArrayList();
    /**
     * List of application resources with this locale
     */
	protected List applicationResources = new ArrayList();
    /**
     * Version of this locale (used in optimistic locking)
     */
	protected Long version;

	/**
	 * Localized title of this locale
	 */
	protected Map title = new HashMap();

	//~ Methods

	/**
	 * Returns the identifier of locale based on standard (for example, en, ru, es, ...)
	 *
	 * @return locale identifier
	 * @struts.validator type="required"
	 * @struts.validator type="mask" msgkey="core.commons.errors.contentLocaleIdentifier"
	 * @struts.validator-args arg0resource="core.contentLocale.form.identifier"
	 * @struts.validator-var name="mask" value="^[a-z]{2}$"
	 * @struts.form-field
	 * @hibernate.id column="`identifier`" generator-class="assigned" unsaved-value="null" length="10"
	 */
	public String getIdentifier() {
		return identifier;
	}

    /**
     * Sets the identifier of locale
     *
     * @param identifier the identifier of locale
     * @see ContentLocale#getIdentifier()
     */
	public void setIdentifier(String identifier) {
		this.identifier = identifier;
	}

	/**
	 * Returns a mapping from locales to titles of this locale (title per each locale)
	 *
	 * @return mapping from locales to titles
	 * @struts.form-field
	 * @hibernate.map table="`al_core_locale_title`" lazy="true" cascade="all" outer-join="false"
	 * @hibernate.collection-key column="`identifier`"
	 * @hibernate.collection-index column="`title_identifier`" type="string" length="10"
	 * @hibernate.collection-element type="string" column="`title`" not-null="false" length="252"
	 */
	public Map getTitle() {
		return title;
	}

    /**
     * Sets a mapping from locales to titles of this locale (title per each locale)
     *
     * @param title mapping from locales to titles
     */
	public void setTitle(Map title) {
		this.title = title;
	}

	/**
	 * Returns version of this content locale
	 *
	 * @return the version
	 * @struts.form-field
	 * @hibernate.version column="`version`" type="long" unsaved-value="null"
	 */
	public Long getVersion() {
		return version;
	}

    /**
     * Sets version of this content locale
     *
     * @param version new version
     */
	public void setVersion(Long version) {
		this.version = version;
	}


	/**
	 * Returns the list of content field values that correspond to this content locale
	 *
	 * @return the list of CFVs
	 * @hibernate.bag name="contentFieldValues" inverse="true" lazy="true" cascade="delete" outer-join="false"
	 * @hibernate.collection-key column="`locale_identifier`"
	 * @hibernate.collection-one-to-many class="com.blandware.atleap.model.core.ContentFieldValue"
	 */
	protected List getContentFieldValues() {
		return contentFieldValues;
	}

    /**
     * Sets list of content field values that correspond to this content locale
     *
     * @param contentFieldValues the list of CFVs
     */
	protected void setContentFieldValues(List contentFieldValues) {
		this.contentFieldValues = contentFieldValues;
	}

	/**
	 * Returns the list of content documents that correspond to this content locale
	 *
	 * @return the list of content documents
	 * @hibernate.bag name="contentDocuments" inverse="true" lazy="true" cascade="delete" outer-join="false"
	 * @hibernate.collection-key column="`locale_identifier`"
	 * @hibernate.collection-one-to-many class="com.blandware.atleap.model.core.ContentDocument"
	 */
	protected List getContentDocuments() {
		return contentDocuments;
	}

    /**
     * Sets list of content documents that correspond to this content locale
     *
     * @param contentDocuments the list of content documents
     */
	protected void setContentDocuments(List contentDocuments) {
		this.contentDocuments = contentDocuments;
	}

	/**
	 * Returns the list of application resources that correspond to this content locale
	 *
	 * @return the list of application resources
	 * @hibernate.bag name="applicationResources" inverse="true" lazy="true" cascade="delete" outer-join="false"
	 * @hibernate.collection-key column="`locale_identifier`"
	 * @hibernate.collection-one-to-many class="com.blandware.atleap.model.core.ApplicationResource"
	 */
	protected List getApplicationResources() {
		return applicationResources;
	}

    /**
     * Sets list of application resources that correspond to this content locale
     *
     * @param applicationResources the list of application resources
     */
	protected void setApplicationResources(List applicationResources) {
		this.applicationResources = applicationResources;
	}

	/**
	 * Returns <code>Boolean.TRUE</code> if this locale is default
	 *
	 * @return whether this locale is default
	 * @hibernate.property column="`default_instance`" not-null="true" type="true_false"
	 */
	public Boolean getDefaultInstance() {
		return defaultInstance;
	}

    /**
     * Sets whether this content locale is default
     *
     * @param defaultInstance whether this locale will be default
     */
	public void setDefaultInstance(Boolean defaultInstance) {
		this.defaultInstance = defaultInstance;
	}

	/**
	 * Returns <code>Boolean.TRUE</code> if this locale is active (and can be
     * used in application for displaying content).
	 *
	 * @return whether this locale is active
	 * @hibernate.property column="`active`" not-null="true" type="true_false"
	 */
	public Boolean getActive() {
		return active;
	}

	/**
	 * Returns <code>true</code> if this locale is active (and can be
     * used in application for displaying content).
	 *
	 * @return whether this locale is active
	 */
	public boolean isActive() {
		return active.booleanValue();
	}

    /**
     * Sets whether this locale will be active.
     *
     * @param active whether this locale will be active
     */
	public void setActive(Boolean active) {
		this.active = active;
	}

	/**
	 * Returns <code>Boolean.TRUE</code> if this locale is enabled (and can be
     * used for editing content).
	 *
	 * @return whether this locale is enabled
	 * @hibernate.property column="`enabled`" not-null="true" type="true_false"
	 */
	public Boolean getEnabled() {
		return enabled;
	}

	/**
	 * Returns <code>true</code> if this locale is enabled (and can be
     * used for editing content).
	 *
	 * @return whether this locale is enabled
	 */
	public boolean isEnabled() {
		return enabled.booleanValue();
	}

    /**
     * Sets whether this locale will be enabled.
     *
     * @param enabled whether this locale will be enabled
     */
	public void setEnabled(Boolean enabled) {
		this.enabled = enabled;
	}

    public boolean equals(Object o) {
		if ( this == o ) {
			return true;
		}
		if ( !(o instanceof ContentLocale) ) {
			return false;
		}

		final ContentLocale contentLocale = (ContentLocale) o;

		if ( identifier != null ? !identifier.equals(contentLocale.identifier) : contentLocale.identifier != null ) {
			return false;
		}

		return true;
	}

	public int hashCode() {
		return (identifier != null ? identifier.hashCode() : 0);
	}

	/**
	 * Compares this locale to another
	 *
	 * @param o Object to compare with. If this object is not an instance of ContentLocale, <code>java.lang.ClassCastException</code> will be thrown
	 * @return a negative integer, zero, or a positive integer as this locale identifier is less than,
	 *         equal to, or greater than the identifier of specified locale.
	 * @see java.lang.Comparable#compareTo(Object)
	 */
	public int compareTo(Object o) {
		if ( o instanceof ContentLocale ) {
			ContentLocale locale = (ContentLocale) o;
			return this.identifier.compareToIgnoreCase(locale.getIdentifier());
		} else {
			throw new ClassCastException("Cannot compare instance of " + getClass().getName() + " to the instance of " + o.getClass().getName());
		}
	}

	/**
	 * Returns shallow copy of this object
     * 
	 * @return Copy of this locale without linked collections
	 */
	public ContentLocale shallowCopy() {
		ContentLocale locale = new ContentLocale();
		locale.setIdentifier(this.identifier);
		// copy title
		Map title = new HashMap();
		for ( Iterator i = this.title.entrySet().iterator(); i.hasNext(); ) {
			Map.Entry entry = (Map.Entry) i.next();
			String key = (String) entry.getKey();
			String value = (String) entry.getValue();
			title.put(key, value);
		}
		locale.setTitle(title);
		locale.setActive(this.active);
		locale.setEnabled(this.enabled);
		locale.setDefaultInstance(this.defaultInstance);
		locale.setVersion(this.version);
		return locale;
	}
}
